package com.wnzt.baszh.core.base;

import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.wnzt.baszh.util.common.GlobalStatic;
import com.wnzt.baszh.util.common.PageHelper;
import com.wnzt.baszh.util.common.SqlTypes;

/**
 * 基础平台业务层数据库操作接口
 * 
 * @version [版本�? 2013-7-11 上午11:12:09]
 */
@Service("commonService")
public class CommonServiceImpl implements ICommonService {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    @Qualifier("commonDao")
    protected ICommonDao commonDao;

    @Override
    public void delete(BaseModel entity) throws Exception {
        this.commonDao.delete(entity);
    }

    @Override
    public void update(BaseModel entity) throws Exception {
        this.commonDao.update(entity);
    }

    @Override
    public void saveOrUpdateList(List<?> entityList) throws Exception {
        this.commonDao.saveOrUpdateList(entityList);
    }

    @Override
    public void merge(BaseModel entity) throws Exception {
        this.commonDao.merge(entity);
    }

    @Override
    public void deleteById(Class<?> c, Serializable id) throws Exception {
        this.commonDao.deleteById(c, id);
    }

    @Override
    public void updateDeleteFlagById(Class<?> c, Serializable id) throws Exception {
        String curSessionUserId = RequestContextHolderUtils.getSession().getAttribute(GlobalStatic.USER_SESSION_ID).toString();
        BaseModel baseModel = this.commonDao.get(c, id);
        baseModel.setDeleteFlag(GlobalStatic.INT_VALUE_1);
        baseModel.setLastUserId(curSessionUserId);
    }

    @Override
    public void deleteList(List<?> entityList) throws Exception {
        this.commonDao.deleteList(entityList);
    }

    @Override
    public Serializable save(BaseModel entity) throws Exception {
        return this.commonDao.save(entity);
    }

    @Override
    public void saveOrUpdate(BaseModel entity) throws Exception {
        this.commonDao.saveOrUpdate(entity);
    }

    @Override
    public int executeHql(String hql, Object... params) throws Exception {
        return this.commonDao.executeHql(hql, params);
    }

    @Override
    public void executeSQL(String sql, Object... values) throws Exception {
        this.commonDao.executeSQL(sql, values);
    }

    @Override
    public List<?> findByHQL(String hql, Object... params) {
        return this.commonDao.findByHQL(hql, params);
    }

    @Override
    public List<?> findBySQL(String sql, Object... params) {
        return this.commonDao.findBySQL(sql, params);
    }

    @Override
    public List<?> findByQBC(DetachedCriteria detachedCriteria) {
        return this.commonDao.findByQBC(detachedCriteria);
    }

    @Override
    public Page findPageByHQL(QueryObject queryObject) {
        return this.commonDao.findPageByHQL(queryObject);
    }

    @Override
    public Page findPageBySQL(QueryObject queryObject) {
        return this.commonDao.findPageBySQL(queryObject);
    }

    @Override
    public Page findPageByQBC(QueryObject queryObject) {
        return this.commonDao.findPageByQBC(queryObject);
    }

    @Override
    public Page findPage(int queryType, QueryObject queryObject) {
        return this.commonDao.findPage(queryType, queryObject);
    }

    @Override
    public BaseModel get(Class<?> c, Serializable id) {
        return this.commonDao.get(c, id);
    }

    @Override
    public BaseModel find(DetachedCriteria detachedCriteria) {
        return this.commonDao.find(detachedCriteria);
    }

    @Override
    public BaseModel find(String hql, Object... params) {
        return this.commonDao.find(hql, params);
    }

    @Override
    public Long getCountByHQL(QueryObject queryObject) {
        return this.commonDao.getCountByHQL(queryObject);
    }

    @Override
    public Long getCountByQBC(DetachedCriteria detachedCriteria) {
        return this.commonDao.getCountByQBC(detachedCriteria);
    }

    @Override
    public Long getCountBySQL(QueryObject queryObject) {
        return this.commonDao.getCountBySQL(queryObject);
    }

    @Override
    public void flush() {
        this.commonDao.flush();
    }

    @Override
    public void clear() {
        this.commonDao.clear();
    }

    @Override
    public List<?> findListByProc(QueryObject queryObject, Map<Integer, Integer> map)throws Exception {
        return this.commonDao.findListByProc(queryObject, map);
    }

    @Override
    public Long getIntID(String tableName, boolean isBigInt) {
        return this.commonDao.getIntID(tableName, isBigInt);
    }

    @Override
    public boolean exists(Class<?> c, Serializable id) {
        return this.commonDao.exists(c, id);
    }

    /**
     * 获取当前数据库操作session对象
     * 
     * @return [参数说明]
     * @return Session
     * @exception throws [违例类型] [违例说明]
     */
    @Override
    public Session getCurrentSession() {
        return this.commonDao.getCurrentSession();
    }
    
    @SuppressWarnings("unchecked")
    public PageHelper queryMssqlSplitPageByProc(final String columns, final String tablenames, final String whereCondition, final String orderColumns, 
            final int isOrderByAsc, final String keyword, final int currentPage, final int pageSize) {
        final PageHelper page = new PageHelper();
        this.jdbcTemplate.execute(new CallableStatementCreator() {
            
            @Override
            public CallableStatement createCallableStatement(Connection conn)
                    throws SQLException {
                String callProc = "{call MsSql2KPagination(?,?,?,?,?,?,?,?,?,?)}";
                CallableStatement cs = conn.prepareCall(callProc);
                cs.setString(1, columns);
                cs.setString(2, tablenames);
                cs.setString(3, whereCondition);
                cs.setString(4, orderColumns);//需要排序的字段
                cs.setInt(5, isOrderByAsc); //0降序  1升序
                cs.setString(6, keyword);
                cs.setInt(7, currentPage);
                cs.setInt(8, pageSize);
                cs.registerOutParameter(9, Types.INTEGER);
                cs.registerOutParameter(10, Types.INTEGER);
                return cs;
            }
        }, new CallableStatementCallback(){

            @Override
            public Object doInCallableStatement(CallableStatement cs)
                    throws SQLException, DataAccessException {
                List<Map<String,Object>> resultmaps = new ArrayList<Map<String,Object>>();
                cs.execute();
                ResultSet rs = cs.getResultSet();
                ResultSetMetaData meta = rs.getMetaData();
                List<String> cols = new ArrayList<String>();
                List<Integer> colstype = new ArrayList<Integer>();
                for(int i=1; i<=meta.getColumnCount(); i++){
                    cols.add(meta.getColumnName(i));
                    colstype.add(meta.getColumnType(i));
                }
                while(rs.next()){
                    Map<String,Object> map = new HashMap<String, Object>();
                    for(int k=1; k<=cols.size(); k++){
                        String col = cols.get(k-1);
                        int coltype = colstype.get(k-1);
                        //System.out.println(col+":"+coltype+":"+rs.getObject(col));
                        switch (coltype) {
                        case SqlTypes.BIT:
                        case SqlTypes.TINYINT:
                        case SqlTypes.SMALLINT:
                        case SqlTypes.INTEGER:
                        case SqlTypes.BIGINT:
                            map.put(col, rs.getInt(k));
                            break;
                        case SqlTypes.FLOAT:
                        case SqlTypes.REAL:
                        case SqlTypes.DOUBLE:
                        case SqlTypes.NUMERIC:
                        case SqlTypes.DECIMAL:
                            map.put(col, rs.getFloat(k));
                            break;
                        case SqlTypes.CHAR:
                        case SqlTypes.VARCHAR:
                        case SqlTypes.LONGVARCHAR:
                        case SqlTypes.NCHAR:
                        case SqlTypes.NVARCHAR:
                        case SqlTypes.LONGNVARCHAR:
                            map.put(col, rs.getString(k));
                            break;
                        case SqlTypes.DATE:
                            map.put(col, rs.getDate(k));
                            break;
                        case SqlTypes.TIME:
                            map.put(col, rs.getTime(k));
                            break;
                        case SqlTypes.TIMESTAMP:
                            map.put(col, rs.getTimestamp(k));
                            break;
                        default:
                            break;
                        }
                    }
                    resultmaps.add(map);
                }
                page.setRows(resultmaps);
                if(!cs.getMoreResults()){
                    Integer total = cs.getInt(10);
                    page.setTotal(total);
                }
                rs.close();
                return page;
            }
            
        });
        return page;
    }
}

